<script lang="ts">
import {defineComponent, computed, ComputedRef, watch, ref} from "vue"
import {TableColumn} from "./TableType"
import ColumnHandle from "./ColumnHandle"
import type {PropType} from 'vue';
import ColumnLabels from "./render/ColumnLabels.vue"
import {CreateKey} from "@/units/system";

export default defineComponent({
  name: "AppTable",
  components: {ColumnLabels},
  emits: {
    //操作按钮事件
    'update:sort': (sort: any) => true,//排序更改触发事件
    'action': (action: string, row: any, index: number) => true,//操作触发事件
    'update': (event: string, value: any, row: any, index: number) => true,//操作触发事件
    'pagination': (page: number, size: number) => true,//分页触发事件
    'reload': (event: { page: number, size: number }) => true,//分页触发事件
    'choice': (primarys: any[], data: any[]) => true//选择数据事件
  },
  props: {
    primaryKey: {//数据主键,涉及到多选
      type: String,
      default: 'id'
    },
    rendering: {//数据变动,重构
      type: Boolean,
      default: false
    },
    data: {//表格数据
      type: Array<any>,
      required: true
    },
    columns: {//表格列配置
      type: Array<TableColumn>,
      required: true
    },
    defaultExpandAll: {//默认展开状态
      type: Boolean,
      default: false
    },
    loading: {//加载状态
      type: Boolean,
      default: false
    },
    pagination: {//分页配置
      type: Object as PropType<{ page: number, size: number, total: number }>
    },
    border: {//显示边框
      type: Boolean,
      default: true
    },
    height: {//表格高度
      type: [String, Number]
    },
    maxHeight: {//表格最大宽度
      type: [String, Number]
    }
  },
  setup(props, {slots, emit}) {
    const tableKey = ref<string>(CreateKey())

    /**
     * 数据变动时重载表格
     */
    if (props.rendering) {
      watch(() => props.data, function () {
        tableKey.value = CreateKey()
      }, {
        deep: true
      })
    }


    /**
     * 表格列配置
     */
    const TableColumn: ComputedRef<Array<any>> = computed(() => {
      return ColumnHandle(props.columns, Object.keys(slots))
    })

    /**
     * 操作按钮事件
     */
    function actionEvent(action: string, row: any, index: number) {
      emit('action', action, row, index)
    }

    /**
     * 分页触发获取数据
     * @param page
     * @param size
     */
    function paginationChange(page: number, size: number) {
      emit('reload', {page, size})
      emit('pagination', page, size)
    }


    /**
     * 多选回调
     */
    function handleSelectionChange(event: any[]) {
      let ids: any[] = event.map(item => item[props.primaryKey])
      emit('choice', ids, event)
    }


    /**
     * 排序触发获取数据
     * @param sort
     */
    function SortChange(sort: any) {
      if (sort.order === 'descending') {
        emit('update:sort', sort.prop)
      } else if (sort.order === 'ascending') {
        emit('update:sort', `-${sort.prop}`)
      } else {
        emit('update:sort', '')
      }
      //@ts-ignore
      emit('reload', {page: props?.pagination?.page, size: props?.pagination?.size})
    }


    /**
     * 触发编辑事件
     */
    function triggerUpdate(event: string, value: any, row: any, index: number) {
      emit('update', event, value, row, index)
    }

    return {
      TableColumn,
      slots,
      actionEvent,
      paginationChange,
      handleSelectionChange,
      SortChange,
      tableKey,
      triggerUpdate
    }
  }
})
</script>
<template>
  <div class="app-table">
    <el-table :key="tableKey" v-bind="$attrs" @sort-change="SortChange" :data="data" :defaultExpandAll :max-height="maxHeight" :height :border v-loading="loading" element-loading-text="玩命加载中" @selection-change="handleSelectionChange">
      <template v-for="column in TableColumn">
        <!--自定义函数方式渲染-->
        <el-table-column v-if="column.render" v-bind="{...column}">
          <template #default="{row,$index}">
            {{ column?.prefix }}{{ column.render(row, $index) }}{{ column?.suffix }}
          </template>
        </el-table-column>
        <!--插槽渲染-->
        <el-table-column v-else-if="slots[column.prop]" v-bind="{...column}">
          <template #default="slotData">
            <slot :name="column.prop" v-bind="slotData"></slot>
          </template>
        </el-table-column>
        <!--折叠渲染-->
        <el-table-column v-else-if="column.type==='expand'" v-bind="{...column}">
          <template #default="slotData">
            <slot name="expand" v-bind="{...slotData}"></slot>
          </template>
        </el-table-column>
        <!--索引渲染-->
        <el-table-column v-else-if="column.type==='index'" v-bind="{...column}">
          <template #default="{$index}">
            <span v-if="pagination && pagination.page">
              {{ column?.prefix }}{{ ($index + 1) + ((pagination.page - 1) * pagination.size) }}{{ column?.suffix }}
            </span>
            <span v-else>

              {{ column?.prefix }}{{ $index + 1 }}{{ column?.suffix }}
            </span>
          </template>
        </el-table-column>
        <!--状态显示渲染-->
        <el-table-column v-else-if="column.type==='status'" v-bind="{...column}">
          <template #default="{row,$index}">
            <app-switch :disabled="!column.edit" :model-value="row[column.prop]" :active-text="column.activeText" :inactive-text="column.inactiveText" @change="triggerUpdate((column?.event?column?.event:column.prop),$event,row,$index)"></app-switch>
          </template>
        </el-table-column>
        <!--多选渲染-->
        <el-table-column v-else-if="column.type==='selection'" v-bind="{...column}"></el-table-column>
        <!--时间戳渲染-->
        <el-table-column v-else-if="column.type==='timestramp'" v-bind="{...column}">
          <template #default="{row}">
            {{ column?.prefix }}
            <show-time v-if="row[column.prop]" :time="row[column.prop]" :format="column.format?column.format:'Y-m-d'"></show-time>
            {{ column?.suffix }}
          </template>
        </el-table-column>
        <!--标签渲染-->
        <el-table-column v-else-if="column.type==='labels'" v-bind="{...column}">
          <template #default="{row}">
            <column-labels :limit="column.limit" :labels="row[column.prop]"/>
          </template>
        </el-table-column>
        <!--图片渲染-->
        <el-table-column v-else-if="column.type==='image'" v-bind="{...column}">
          <template #default="{row}">
            <el-image loading="lazy" lazy class="app-width-p20 app-height-p20" preview-teleported v-if="row[column.prop]" :preview-src-list="[row[column.prop]]" :src="row[column.prop]"/>
          </template>
        </el-table-column>
        <!--Json值获取渲染-->
        <el-table-column v-else-if="column.type==='json'" v-bind="{...column}">
          <template #default="{row}">
            {{ column?.prefix }}
            <json-value :data="row[column.prop]" :property="column.property"></json-value>
            {{ column?.suffix }}
          </template>
        </el-table-column>
        <!--渲染操作-->
        <el-table-column v-else-if="column.type==='action'" v-bind="{...column}">
          <template #default="slotData">
            <slot name="action" v-bind="slotData">
              <el-space size="small">
                <operate-link v-if="column.update" @tap="actionEvent('update',slotData.row,slotData.$index)">
                  编辑
                </operate-link>
                <operate-link confirm="确定要删除选中数据吗?" @tap="actionEvent('remove',slotData.row,slotData.$index)" v-if="column?.remove">
                  删除
                </operate-link>
              </el-space>
            </slot>
          </template>
        </el-table-column>
        <!--长文本渲染-->
        <el-table-column v-else-if="column.type==='long-text'" v-bind="{...column}">
          <template #default="{ row }">
            <el-tooltip effect="dark">
              <template #content>
                <el-scrollbar style="max-width: 250px;" max-height="150px">
                  {{ column?.prefix }}{{ row[column.prop] }}{{ column?.suffix }}
                </el-scrollbar>
              </template>
              <template #default>
                <span class="long-text">
                  {{ column?.prefix }}{{ row[column.prop] }}{{ column?.suffix }}
                </span>
              </template>
            </el-tooltip>
          </template>
        </el-table-column>
        <!--默认渲染start-->
        <el-table-column v-else v-bind="{...column}">
          <template #default="{ row }">
            {{ column?.prefix }}{{ row[column.prop] }}{{ column?.suffix }}
          </template>
        </el-table-column>
      </template>
    </el-table>
    <slot name="pagination">
      <div v-if="pagination" class="app-margin-top-medium">
        <app-pagination :disabled="loading" v-bind="pagination" @change="paginationChange"></app-pagination>
      </div>
    </slot>
  </div>
</template>
<style scoped lang="scss">
.long-text {
  display: block;
  box-sizing: border-box;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
</style>